﻿using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Text.RegularExpressions;

namespace BioInfSearch
{
	public partial class _Default : System.Web.UI.Page
	{
		const int pubmedQpp = 5;
		const int pmcQpp = 3;

		public enum SearchType { Info, Sequence, Both };
		protected void Page_Load(object sender, EventArgs e)
		{
			resultbar.EnableViewState = false;
		}

		protected void btnSearch_Click(object sender, EventArgs e)
		{
			SearchType sType;
			string strQuery = query.Value.ToLower();
			curpage.Value = "0";
			prepQuery(ref strQuery);
			sType = determineSearchType(strQuery);
			runQuery(sType, strQuery, null);
		}

		private void runQuery(SearchType sType, string strQuery, string[] pageparams)
		{
			switch (sType)
			{
				case SearchType.Info:
					SearchByTerm(strQuery, pageparams);
					break;
				case SearchType.Sequence:
					SequenceSearch(strQuery);
					break;
				case SearchType.Both:
					break;
				default:
					break;
			} //end switch
		}

		private void SearchById(string id)
		{
			string[] ids = { "9298984" };
			//eUtils.eLinkResultType similar  = run
			eUtils.eUtilsService serv = new eUtils.eUtilsService();

			// call NCBI ELink utility

			eUtils.eLinkResultType res = serv.run_eLink_MS("", ids, "", "", "", "", "", "pubmed", "", "", "neighbor", "", "");

			string pmids = "";

			for (int i = 0; i < res.LinkSet[0].IdList.Length; i++)
			{
				pmids += res.LinkSet[0].IdList[i].Value + ",";
			}

			InfoSearch(ids.ToString(), "", "", "");
		}

		private void SearchByTerm(string strQuery, string[] pageparams)
		{
			eUtils.eUtilsService serv = new eUtils.eUtilsService();

			if (pageparams == null)
				pageparams = new string[] { "0", "5", "0", "3" };
			// call NCBI ESearch utility
			// NOTE: search term should be URL encoded 
			eUtils.eSearchResultType pubmedResult = runSearch("pubmed", HttpUtility.UrlEncode(strQuery), pageparams[0], pageparams[1], serv);
			eUtils.eSearchResultType pmcResult = runSearch("pmc", HttpUtility.UrlEncode(strQuery) + "+AND+free+fulltext[filter]", pageparams[2], pageparams[3], serv);

			string strPubmedIDs = String.Join(",", pubmedResult.IdList);
			string strPmcIDs = String.Join(",", pmcResult.IdList);

			string spellSuggestion = checkSpelling(strQuery);
			if (spellSuggestion == strQuery)
				spellSuggestion = "";

			InfoSearch(strPubmedIDs, strPmcIDs, spellSuggestion, strQuery);
		}

		private void InfoSearch(string strPubmedIDs, string strPmcIDs, string spellCorrection, string query)
		{
			// search in PubMed Central query
			string title;
			string jtitle;
			string pmid;
			string tabstract;

			try
			{
				eUtils.eUtilsService serv = new eUtils.eUtilsService();
				resultbar.Attributes.Remove("style");
				resultbar.Attributes.Add("style", @"visibility:visible; border:solid 1px green");

				resultbar.InnerHtml = "Results for <b>" + query + "</b>";
				results.InnerHtml = "";

				//pubmed results
				if (!string.IsNullOrEmpty(spellCorrection))
				{
					resultbar.InnerHtml += " Did you mean: <a href=\"javascript:query('" + spellCorrection + "');\">" + spellCorrection + "</a>";
				}
				resultbar.Controls.Add(navbar);

				// call NCBI EFetch utility and get abstracts
				if (strPubmedIDs.Length > 0)
				{
					eUtils.eFetchResultType pubmedFetchResults = runFetch("pubmed", strPubmedIDs, serv);

					for (int i = 0; i < pubmedFetchResults.PubmedArticleSet.Length; i++)
					{
						title = pubmedFetchResults.PubmedArticleSet[i].MedlineCitation.Article.ArticleTitle;
						if (query.Length > 0)
						{
							Regex tr = new Regex(query, RegexOptions.IgnoreCase);

							title = tr.Replace(title, "<b>" + query + "</b>");
							//title = title.Replace(tr, "<b>" + query + "</b>");
						}
						//results from pubmed
						results.InnerHtml += @"<div class=""article"">";
						results.InnerHtml += @"<div class=""titlebar"">" + title + " <a target=\"_blank\" href=\"http://www.ncbi.nlm.nih.gov/pubmed/" + pubmedFetchResults.PubmedArticleSet[i].MedlineCitation.PMID + "\">Full text</a></div>";
						results.InnerHtml += @"<div class=""info"">Journal: " + pubmedFetchResults.PubmedArticleSet[i].MedlineCitation.Article.Journal.Title + "<br />";
						results.InnerHtml += @"PubMed ID: " + pubmedFetchResults.PubmedArticleSet[i].MedlineCitation.PMID + "</div><a class=\"toggleAbstract\" href=\"#\">Show abstract &raquo;</a>";
						if (pubmedFetchResults.PubmedArticleSet[i].MedlineCitation.Article.Abstract != null)
						{
							results.InnerHtml += "<div class=\"abstract\"><b>Abstract: </b>" + pubmedFetchResults.PubmedArticleSet[i].MedlineCitation.Article.Abstract.AbstractText + "</div>";
						}
						else
							results.InnerHtml += "<div class=\"abstract\"><b>Abstract:</b> Not available " + "</div>";
						results.InnerHtml += "</div>";
					}
				}

				if (strPmcIDs.Length > 0)
				{
					eUtils.eFetchResultType pmcFetchResults = runFetch("pmc", strPmcIDs, serv);

					for (int i = 0; i < pmcFetchResults.pmcarticleset.Length; i++)
					{

						title = pmcFetchResults.pmcarticleset[i].front.articlemeta.titlegroup.articletitle.Text[0];

						if (query.Length > 0)
						{
							Regex tr = new Regex(query, RegexOptions.IgnoreCase);
							title = tr.Replace(title, "<b>" + query + "</b>");
							//title = title.Replace(tr, "<b>" + query + "</b>");
						}
						jtitle = pmcFetchResults.pmcarticleset[i].front.journalmeta.journaltitle[0].Text[0];
						pmid = pmcFetchResults.pmcarticleset[i].front.articlemeta.articleid[0].Text[0];
						results.InnerHtml += @"<div class=""article"">";
						results.InnerHtml += @"<div class=""titlebar"">" + title + " <a href=\"http://www.pubmedcentral.nih.gov/articlerender.fcgi?tool=pmcentrez&artid=" + strPmcIDs.Split(',')[i] + "\" target=\"_blank\">Full text</a></div>";
						results.InnerHtml += @"<div class=""info"">Journal: " + jtitle + "<br />";
						results.InnerHtml += @"PubMed Central ID: " + pmid + "<br />";
						results.InnerHtml += "</div></div>";
					}
				}

			}
			catch (Exception e)
			{
				results.InnerHtml = e.Message;
			}

		}

		//private BioInfSearch.eUtils.eFetchResultType


		private BioInfSearch.eUtils.eFetchResultType runFetch(string db, string strIds, eUtils.eUtilsService serv)
		{
			return serv.run_eFetch_MS(db, strIds, "", "",
													"", "", "", "", "", "", "", "", "", "");
		}
		private eUtils.eSearchResultType runSearch(string db, string query, string min, string max, eUtils.eUtilsService serv)
		{
			return serv.run_eSearch_MS(db, query, "", "", "", "", "", "", "", "", "", "", min, max, "", "");
		}

		private void SequenceSearch(string strQuery)
		{

		}

		private SearchType determineSearchType(string strQuery)
		{
			const string pattern = @"[a,c,t,g]*";
			Match match;
			match = Regex.Match(strQuery, pattern);
			if (match.Groups.Count > 0 && match.Groups[0].Length > 20)
			{
				//sequence!
				return SearchType.Sequence;
			}
			else
				return SearchType.Info;
		}

		private void prepQuery(ref string strQuery)
		{
			strQuery.Trim();

		}

		private string checkSpelling(string term)
		{
			eUtils.eUtilsService serv = new eUtils.eUtilsService();

			eUtils.eSpellResultType res = serv.run_eSpell_MS("pubmed", HttpUtility.UrlEncode(term), "", "");

			return res.CorrectedQuery;
		}

		protected void prev_Click(object sender, EventArgs e)
		{
			SearchType sType;
			string strQuery;
			string[] pageparams;
			int[] pages = new int[4];
			
			int page = Convert.ToInt32(curpage.Value);
			if (page == 0)
			{
				resultbar.Attributes.Remove("style");
				resultbar.Attributes.Add("style", @"visibility:visible; border:solid 1px green");
				resultbar.InnerHtml = "Results";
				resultbar.Controls.Add(navbar);
				return;
			}
			else
			{
				curpage.Value = (--page).ToString();
				pagedisp.InnerText = curpage.Value;
				pages[0] = page * pubmedQpp;
				pages[1] = pubmedQpp;
				pages[2] = page * pmcQpp;
				pages[3] = pmcQpp;

				strQuery = query.Value.ToLower();
				prepQuery(ref strQuery);
				sType = determineSearchType(strQuery);
				pageparams = new string[] { pages[0].ToString(), pages[1].ToString(), pages[2].ToString(), pages[3].ToString() };

				runQuery(sType, strQuery, pageparams);
			}
		}

		protected void next_Click(object sender, EventArgs e)
		{
			SearchType sType;
			string strQuery;
			string[] pageparams;
			int[] pages = new int[4];
			int page = Convert.ToInt32(curpage.Value);

			curpage.Value = (++page).ToString();
			pagedisp.InnerText = curpage.Value;
			pages[0] = page * pubmedQpp;
			pages[1] = pubmedQpp;
			pages[2] = page * pmcQpp;
			pages[3] = pmcQpp;

			strQuery = query.Value.ToLower();
			prepQuery(ref strQuery);
			sType = determineSearchType(strQuery);
			pageparams = new string[] { pages[0].ToString(), pages[1].ToString(), pages[2].ToString(), pages[3].ToString() };

			runQuery(sType, strQuery, pageparams);
		}

	}
}
